home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
source
/
music4c.sit
/
Music4C Folder
/
Sources Folder
/
pass3.c
< prev
next >
Wrap
Text File
|
1990-09-09
|
14KB
|
656 lines
/*
* ⌐ Graeme Gerrard 1990
* Faculty of Music, University of Melbourne
* Parkville Victoria 3052 Australia.
*
* ARPANET: grae@murdu.ucs.unimelb.edu.au
* telephone: (613) 344 4127, Fax: (613) 344 5346
*/
#include "Music4C.h"
#include <math.h>
#include <unix.h>
#include "Music4C_Prototype.h"
#include "ErrorAlert.h"
Boolean pass3(void);
void init_funcs(void);
void free_funcs(void);
void initl(void);
void setup(void);
void orch(void);
void ter(void);
void final(void);
void fread_card(void);
Boolean play(void);
void ClosePass3Input(void);
void calcPeakAndSOR(void);
void insert(void);
void gen(int, double *);
void remove_instr(void);
Boolean spend(void);
void report_sect_time(void);
void report_end_time(void);
void calcPeakAndSOR(void);
Boolean samout(void);
void check_params(void);
extern Boolean Mac_write3(float *, float);
void dump_samps(void);
extern void tell_mem(void);
float *SampsPtr;
static long start_time; /* for counting elapsed time */
static long end_time;
static long sect_start_time;
static long sect_end_time;
static int sectnum; /* section number */
int nrec; /* record count */
double tt; /* time from start of run */
double t; /* time from start of section */
static int nseg[MAXCHANS]; /* samples out of range for segment */
static int nsect[MAXCHANS]; /* samples out of range per section */
static int ntot[MAXCHANS]; /* samps out of range for run */
static double sect[MAXCHANS]; /* max amp per section*/
static double seg[MAXCHANS]; /* max amplitude for segment */
static double peak[MAXCHANS]; /* max amplitude for run */
double *p; /* parameter array */
double *out; /* storage for samples */
int wrote_rec; /* flag indicating a record has been written to disk */
int opcode; /* opcode */
int npargs; /* number of parameter arguments */
int insno;
int instype;
static double delay; /* delay, in number of samples, to end of segment */
int loc; /* pointer to out array for basic channel */
static int iloc;
static int length;
extern Str255 p2tmp;
int samps_file; /* fd for pass3 sample file */
extern OSErr theErr;
extern Str255 theMess1, theMess2;
typedef struct Instr_info {
int i_type;
int i_index;
struct Instr_info *next;
} Instr_info;
Instr_info *i_list; /* linked list to record instruments on/off */
Boolean pass3()
{
extern double srate;
extern int out3_flag;
extern int RunToPass3;
extern int max_ins_types;
extern int nchnls;
register int i;
extern Str255 sfile; /* name of sound file */
double st;
/* overall maximum and minimum amplitudes for use in resource file */
extern float MaxSample;
extern float MinSample;
extern int SFvRefNum;
extern FILE *p2out;
extern char aString1[MAXSTRING];
extern char aString2[MAXSTRING];
MaxSample = 0.0;
MinSample = 0.0;
start_time = TickCount();
p = (double *)NewPtr(MAXPARAMS * sizeof(double));
if ( (theErr = MemError()) != noErr ){
PstringCopy((char *)theMess1, "\pError allocating parameter buffer memory in pass3");
OSError(theMess1, NIL, theErr);
}
out = (double *)NewPtr(SAMPBUFSZ * sizeof(double));
if ( (theErr = MemError()) != noErr ){
PstringCopy((char *)theMess1, "\pError allocating out buffer memory in pass3");
OSError(theMess1, NIL, theErr);
}
SampsPtr = (float *)NewPtr(SAMPBUFSZ * sizeof(float));
if ( (theErr = MemError()) != noErr ){
PstringCopy((char *)theMess1, "\pError allocating sample buffer memory in pass3");
OSError(theMess1, NIL, theErr);
}
rewind(p2out);
init_funcs();
iloc = 0;
nrec = 0;
sectnum = 0;
initl();
tell_mem();
tt = 0.0;
for ( i = 0; i < MAXCHANS; i++ ) {
nsect[i] = 0;
nseg[i] = 0;
sect[i] = 0.0;
seg[i] = 0.0;
peak[i] = 0.0;
}
opcode = 0;
if ( out3_flag) {
Report("\n");
Report("\n");
Report("Pass3 output\n");
}
do {
sect_start_time = TickCount();
sectnum++;
t = 0.0;
if ( out3_flag) {
sprintf((char *)theMess1, "Section %d\n", sectnum);
Report((char *)theMess1);
}
do {
fread_card();
if ( opcode == IOP || opcode == ENDOP )
st = p[2];
else
st = p[1];
delay = srate * (st - t);
if ( delay >= 1.0 ) { /* play up to end of current segment */
if ( !play() ) {
DisposPtr((Ptr)SampsPtr);
ClosePass3Input();
free_funcs();
return(FALSE);
}
tt += (st - t);
if ( out3_flag) {
sprintf((char *)theMess1, "t%10f ...%10f\ttt%10f", t, st, tt);
Report((char *)theMess1);
}
for ( i = 0; i < nchnls; i++ ) {
if ( out3_flag) {
sprintf((char *)theMess1, "\t%10f", seg[i] );
Report((char *)theMess1);
}
sect[i] = MAX(sect[i], seg[i]);
seg[i] = 0.0;
}
if ( out3_flag)
Report("\n");
if ( (nseg[0] + nseg[1] + nseg[2] + nseg[3]) > 0 ) {
if ( out3_flag)
Report("No. of samples out of range\t\t\t\t");
for ( i = 0; i < nchnls; i++ ) {
if ( out3_flag) {
sprintf((char *)theMess1, "\t%d", nseg[i]);
Report((char *)theMess1);
}
nsect[i] += nseg[i];
nseg[i] = 0;
}
if ( out3_flag)
Report("\n");
}
}
t = st;
/* tell_mem();*/
if ( opcode == IOP )
insert();
else if ( opcode == FOP )
gen(npargs, p);
else if ( opcode == ENDOP ) {
remove_instr();
ter();
}
} while ( opcode != SOP && opcode != EOP );
if (opcode == EOP) {
if (!spend() ) {
DisposPtr((Ptr)SampsPtr);
free_funcs();
return(FALSE);
}
}
report_sect_time();
} while ( opcode != EOP );
if (!spend() ) {
DisposPtr((Ptr)SampsPtr);
free_funcs();
return(FALSE);
}
report_end_time();
free_funcs();
ClosePass3Input();
DisposPtr((Ptr)SampsPtr);
final();
calcPeakAndSOR();
return(TRUE);
}
void remove_instr()
{
/* delete instrument from queue, it has finished playing */
Instr_info *cursor;
Instr_info *prev;
Instr_info *toDelete;
cursor = i_list;
prev = i_list;
instype = (int)p[0];
insno = (int)p[1];
while ( cursor != NIL ) {
if ( cursor->i_type == instype && cursor->i_index == insno ) {
/* found the instr, delete it from list */
if ( cursor == i_list ) { /* list head */
toDelete = i_list;
if ( i_list->next )
i_list = i_list->next;
/* only 1 instrument ?*/
else
i_list = NIL;
DisposPtr((Ptr)toDelete);
}
else {
toDelete = cursor;
prev->next = cursor->next;
DisposPtr((Ptr)toDelete);
}
break;
}
else {
prev = cursor;
cursor = cursor->next;
}
}
}
void insert()
{
/* enter the instrument in queue */
extern int max_ins_types;
Instr_info *cursor;
Instr_info *prev;
Instr_info *newInstr;
cursor = i_list;
prev = i_list;
instype = (int)p[0];
insno = (int)p[1];
while ( cursor != NIL ) {
if ( cursor->i_type == instype && cursor->i_index == insno ) {
sprintf(aString1, "Instrument type %d, instrument %d, ",
instype, insno);
sprintf(aString2, "at start time = %f", p[2]);
CtoPstr(aString2);
CtoPstr(aString1);
PstringCat((char *)theMess1, (char *)aString1);
PstringCat((char *)theMess1, (char *)aString2);
PstringCopy((char *)theMess2, "\pis already playing");
OSError(theMess1, theMess2, NIL);
}
prev = cursor;
cursor = cursor->next;
}
newInstr = (Instr_info *)NewPtr(sizeof(Instr_info));
if ( (theErr = MemError()) != noErr ){
PstringCopy((char *)theMess1, "\pError allocating memory in insert");
OSError(theMess1, theMess2, NIL);
}
newInstr->next = NIL;
newInstr->i_type = instype;
newInstr->i_index = insno;
if ( i_list == NIL)
i_list = newInstr;
else
prev->next = newInstr;
setup();
if ( instype > max_ins_types ) {
sprintf(aString1, "No such instrument type no. = %d", instype);
sprintf(aString2, " (start time %f)", p[2] );
CtoPstr(aString1);
CtoPstr(aString2);
PstringCopy((char *)theMess1, (char *)aString1);
PstringCopy((char *)theMess2, (char *)aString2);
OSError(theMess1, theMess2, NIL);
}
}
Boolean play()
{
extern int dump_samps_flag;
double *sptr;
register int i;
register int j;
long nsamps;
extern int nchnls;
double x;
Instr_info *cursor;
extern double rescalingConst;
cursor = i_list;
/* determine number of samples in the next time segment */
nsamps = ((long) (delay + 0.5) ) * nchnls;
while ( nsamps > 0L ) {
nsamps -= SAMPBUFSZ;
if ( nsamps < 0L ) {
length = (int)nsamps + SAMPBUFSZ;
for ( i = 0, sptr = out; i < SAMPBUFSZ; i++ )
*sptr++ = 0.0;
}
else {
length = SAMPBUFSZ;
sptr = out;
for ( i = 0; i < length; i++)
*sptr++ = 0.0;
}
if ( i_list != NIL ) {
for ( i = 0; i < length; i += nchnls ) {
loc = i;
cursor = i_list;
while ( cursor != NIL ) {
instype = cursor->i_type;
insno = cursor->i_index;
orch();
cursor = cursor->next;
}
}
if ( rescalingConst > 0.0 ) {
for ( i = 0, sptr = out; i < length; i++ )
*sptr++ *= rescalingConst;
}
for ( i = 0; i < length; i += nchnls ) {
for ( j = 0; j < nchnls; j++ ) {
x = fabs(out[i+j]);
if ( x > SAMPMAX )
nseg[j]++;
if ( x > seg[j] )
seg[j] = x;
if ( seg[j] > peak[j] )
peak[j] = seg[j];
}
}
}
wrote_rec = 0;
if (!samout() ) {
return(FALSE);
}
}
return(TRUE);
}
void report_sect_time()
{
register int i;
long secs;
int mins;
sect_end_time = TickCount();
secs = (long)(sect_end_time - sect_start_time) / 60L;
mins = secs / 60;
if ( mins > 0 ) {
if ( out3_flag ) {
sprintf((char *)theMess1, "End of section %d, synthesis time was %d mins %ld secs\n",
sectnum, mins, secs - (mins * 60));
Report((char *)theMess1);
}
}
else {
if ( out3_flag ) {
sprintf((char *)theMess1, "End of section %d, synthesis time was %ld secs\n",
sectnum, secs );
Report((char *)theMess1);
}
}
if ( out3_flag )
Report("Maximum amplitude per channel was\n");
for ( i = 0; i < nchnls; i++ ) {
if ( out3_flag ) {
sprintf( (char *)theMess1, "\t\t\t\t\t\tchannel %d\t%f\n", i+1, sect[i] );
Report((char *)theMess1);
}
peak[i] = MAX(peak[i], sect[i]);
sect[i] = 0.0;
}
if ( out3_flag )
Report("\n");
if ( (nsect[0] + nsect[1] + nsect[2] + nsect[3]) > 0 ) {
if ( out3_flag )
Report("No. of samples out of range\t\t\t\t");
for ( i = 0; i < nchnls; i++ ) {
if ( out3_flag ) {
sprintf((char *)theMess1, "\t%d", nsect[i]);
Report((char *)theMess1);
}
ntot[i] += nsect[i];
nsect[i] = 0;
}
if ( out3_flag )
Report("\n");
}
}
void report_end_time()
{
long secs;
int mins;
end_time = TickCount();
secs = (long)(end_time - start_time) / 60L;
mins = secs / 60;
if ( mins > 0 ) {
if ( out3_flag ) {
Report("End of Pass3\n");
sprintf((char *)theMess1, "Total synthesis time was\t\t%d mins %ld secs\n", mins, secs - (mins * 60));
Report((char *)theMess1);
}
}
else {
if ( out3_flag ) {
Report("End of Pass3\n");
sprintf((char *)theMess1, "Total synthesis time was \t\t\t%ld secs\n", secs );
Report((char *)theMess1);
}
}
}
void calcPeakAndSOR()
{
register int i;
double x = 0.0;
double r = 0.0;
for ( i = 0; i < nchnls; i++ )
x = MAX(x, peak[i]);
r = SAMPMAX / x;
if ( out3_flag ) {
sprintf((char *)theMess1, "Overall peak amplitude was \t\t\t%f\n", x);
Report((char *)theMess1);
sprintf((char *)theMess1, "Rescaling constant\t\t\t\t\t%f\n", r );
Report((char *)theMess1);
}
if ( out3_flag ) {
if ( (ntot[0] + ntot[1] + ntot[2] + ntot[3]) > 0 ) {
Report("Sum of samples out of range\t\t\t\t");
for ( i = 0; i < nchnls; i++ ) {
sprintf( (char *)theMess1, "\t%d", ntot[i]);
Report((char *)theMess1);
}
Report("\n");
}
}
}
void ClosePass3Input()
{
int i;
i = fclose(p2out);
i = remove((char *)p2tmp); /* ??? */
}
void fread_card()
{
/* read an event record from the pass3 input file. Remember,
* this has been sorted chronologically by pass2
*/
register int i;
register int k;
extern FILE *p2out;
i = fread(&opcode, sizeof(int), 1, p2out);
if ( opcode == SOP || opcode == EOP ) {
i = fread(p, sizeof(double), 1, p2out);
p[1] = p[0];
}
else if ( opcode == ENDOP ) {
i = fread(p, sizeof(double), 3, p2out); /* get instype, insno, end time */
}
else if ( opcode == NULLOP ) {
npargs = 0;
}
else {
i = fread(&npargs, sizeof(int), 1, p2out);
k = fread(p, sizeof(double), npargs, p2out);
}
}
void check_params()
{
register int i;
if ( out3_flag ) {
sprintf( (char *)theMess1, "opcode = %d\n", opcode );
Report((char *)theMess1);
for ( i = 0; i < npargs; i++ ) {
sprintf( (char *)theMess1, "\tp[%d] = %f\n", i, p[i]);
Report((char *)theMess1);
}
}
}
Boolean spend()
{
/* clear remainder of last output record before writing it to file */
register int i;
register float *sptr;
if (!wrote_rec) {
sptr = (SampsPtr + iloc);
for ( i = iloc; i < SAMPBUFSZ; i++ )
*sptr++ = 0.0;
if ( iloc < SAMPBUFSZ)
--sptr;
if (!Mac_write3(SampsPtr, tt)) {
return(FALSE);
}
return(TRUE);
}
return(TRUE);
}
Boolean samout()
{
/* append the newly generated samples to the output buffer,
* and call to write buffer to soundfile
*/
extern float MaxSample;
extern float MinSample;
register int i;
double *optr;
float *sptr;
optr = out;
sptr = (SampsPtr + iloc);
for ( i = 0; i < length; i++) {
*sptr = (float)*optr++;
if ( *sptr > MaxSample)
MaxSample = *sptr;
if ( *sptr < MinSample )
MinSample = *sptr;
iloc++;
if ( dump_samps_flag )
dump_samps();
if ( iloc == SAMPBUFSZ ) {
if (!Mac_write3(SampsPtr, tt)) {
return(FALSE);
}
iloc = 0;
sptr = SampsPtr;
}
else
sptr++;
}
if ( iloc < SAMPBUFSZ)
--sptr;
return(TRUE);
}
/*
this from old unix version
write3()
{
register int i;
unsigned towrite = SAMPBUFSZ * sizeof(float);
nrec++;
if ( CreateSoundFile ) {
if ( (i = write(samps_file, (char *)SampsPtr, towrite)) != towrite)
fprintf(stderr, "error writing sample buffer in write3, error %d\n", i);
}
fprintf(stderr, "write3, rec no%d\n", nrec);
wrote_rec = 1;
}
*/
void dump_samps()
{
}
/*----------------------------------------------------------------------------*/